1026 lines
28 KiB
C
1026 lines
28 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*****************************************************************************
|
|
*
|
|
* File: WmFP.c
|
|
*
|
|
* Project: CDE
|
|
*
|
|
* Description: This file contains functions used between the window manager
|
|
* and front panel.
|
|
*
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
* (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
#include "WmGlobal.h"
|
|
|
|
|
|
#include <Dt/DtP.h>
|
|
#include <Dt/DbReader.h>
|
|
#include <Dt/Control.h>
|
|
#include <Dt/ControlP.h>
|
|
#include <Dt/IconFile.h>
|
|
#include <Dt/Icon.h>
|
|
#include <Dt/Wsm.h>
|
|
#include <Dt/MacrosP.h>
|
|
|
|
#include <Xm/Form.h>
|
|
#include <Xm/ToggleBG.h>
|
|
#include <Xm/MwmUtil.h>
|
|
#include <Xm/AtomMgr.h>
|
|
#include <Xm/DrawingA.h>
|
|
#include <Xm/RowColumn.h>
|
|
#include <Xm/SeparatoG.h>
|
|
#include <Xm/DialogS.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
#include <X11/keysymdef.h>
|
|
|
|
#include "PanelSP.h"
|
|
#include "DataBaseLoad.h"
|
|
#include "UI.h"
|
|
|
|
#include "WmPanelP.h"
|
|
#include "WmManage.h"
|
|
|
|
#include <pwd.h>
|
|
#include <fcntl.h>
|
|
#include <stdint.h>
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
extern void SubpanelTornEventHandler (Widget, XtPointer, XEvent *, Boolean *);
|
|
extern void WorkspaceModifyCB (Widget, Atom, int, XtPointer);
|
|
extern void SessionRestoreData (void);
|
|
extern void UnManageWindow (ClientData *pCD);
|
|
extern void WorkspaceAdjustPanelPosition (Position x,
|
|
Position y,
|
|
Dimension width,
|
|
Dimension height);
|
|
|
|
static void PushRecallSetData ();
|
|
static void EmbeddedClientSetData ();
|
|
static void EmbeddedClientSetGeometry (WmFpEmbeddedClientData *);
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* EmbeddedClientReposition
|
|
* This function moves client windows within the main panel after
|
|
* controls have been resized.
|
|
*
|
|
* Inputs: icon - the icon of the embedded client to be repositioned
|
|
* x - the position of the resized control
|
|
* adjust - how much to move the window
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
EmbeddedClientReposition (Widget icon,
|
|
Position x,
|
|
Dimension adjust)
|
|
|
|
|
|
|
|
{
|
|
WmFpEmbeddedClientList embedded_client_list =
|
|
(WmFpEmbeddedClientList) panel.embedded_client_list;
|
|
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < panel.embedded_client_count; i++)
|
|
{
|
|
if (XtParent (icon) == XtParent (embedded_client_list[i].wControl) &&
|
|
embedded_client_list[i].x > x)
|
|
{
|
|
if (embedded_client_list[i].pCD != NULL)
|
|
{
|
|
embedded_client_list[i].x += adjust;
|
|
XMoveWindow (XtDisplay (panel.shell),
|
|
embedded_client_list[i].pCD->client,
|
|
embedded_client_list[i].x, embedded_client_list[i].y);
|
|
}
|
|
else
|
|
embedded_client_list[i].x += adjust;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* EmbeddedClientReparent
|
|
* This function sets of the data necessary to call the window
|
|
* manager function which reparents an embedded client to a new
|
|
* control.
|
|
*
|
|
* Inputs: client_name - the name of the client to be reparented.
|
|
* icon - the widget that is to contain the client.
|
|
* parent_win - the parent win to reparent the client to.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
EmbeddedClientReparent (char * client_name,
|
|
Widget icon)
|
|
|
|
|
|
{
|
|
WmFpEmbeddedClientList embedded_client_list =
|
|
(WmFpEmbeddedClientList) panel.embedded_client_list;
|
|
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < panel.embedded_client_count; i++)
|
|
{
|
|
if (strcmp (client_name, embedded_client_list[i].pchResName) == 0)
|
|
break;
|
|
}
|
|
|
|
|
|
/* Try to reparent the client to/from the main panel. If this */
|
|
/* fails, it is because of a dtwm restart and the clients have */
|
|
/* not yet been grabbed. So just reset the embedded client data */
|
|
|
|
if (ReparentEmbeddedClient (&embedded_client_list[i], icon,
|
|
XtWindow (XtParent (icon)),
|
|
XtX (icon) + 3, XtY (icon) + 3,
|
|
XtWidth(icon) - 6, XtHeight(icon) - 6) == False)
|
|
{
|
|
embedded_client_list[i].wControl = icon;
|
|
embedded_client_list[i].winParent = XtWindow (XtParent (icon));
|
|
embedded_client_list[i].x = XtX (icon) + 3;
|
|
embedded_client_list[i].y = XtY (icon) + 3;
|
|
embedded_client_list[i].width = XtWidth (icon) - 6;
|
|
embedded_client_list[i].height = XtHeight (icon) - 6;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* EmbeddedClientRegister
|
|
* This function adds a control to the list of embedded client controls
|
|
* and resets, if necessary, the Window Managers pointers to the list.
|
|
*
|
|
* Inputs:
|
|
* control_data - the pointer to the ControlData * structure of
|
|
* the control to be installed or removed.
|
|
*
|
|
* install - Boolean indicating whether to add or remove the control
|
|
* from the push recall list.
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
EmbeddedClientRegister (ControlData * control_data,
|
|
Boolean install)
|
|
|
|
|
|
{
|
|
char * client_name;
|
|
Window client_window;
|
|
int i, j;
|
|
|
|
WmFpEmbeddedClientList embedded_client_list =
|
|
(WmFpEmbeddedClientList) panel.embedded_client_list;
|
|
|
|
WmFpEmbeddedClientData * embedded_client = NULL;
|
|
|
|
if ((intptr_t) control_data->
|
|
element_values[CONTROL_TYPE].parsed_value != CONTROL_CLIENT)
|
|
return;
|
|
|
|
|
|
/* If this is a control installation, increase the list size, if */
|
|
/* needed, and initialize the embedded client structure. If it is */
|
|
/* a removal, find the control in the list and remove it by sliding */
|
|
/* each subsequent structure down one element in array. */
|
|
|
|
client_name = (char *)
|
|
control_data->element_values[CONTROL_CLIENT_NAME].parsed_value;
|
|
|
|
if (client_name == NULL)
|
|
client_name = (char *)
|
|
control_data->element_values[CONTROL_LABEL].parsed_value;
|
|
|
|
if (install)
|
|
{
|
|
|
|
/* First see if this is an update to an already installed */
|
|
/* embedded client. If so, simply update the icon field */
|
|
|
|
for (i = 0; i < panel.embedded_client_count; i++)
|
|
{
|
|
if (strcmp (client_name, embedded_client_list[i].pchResName) == 0)
|
|
{
|
|
embedded_client_list[i].wControl = control_data->icon;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= panel.embedded_client_count)
|
|
{
|
|
if (panel.embedded_client_count == panel.max_embedded_client_count)
|
|
{
|
|
panel.max_embedded_client_count += 10;
|
|
embedded_client_list = (WmFpEmbeddedClientList)
|
|
XtRealloc ((char *) embedded_client_list,
|
|
sizeof (WmFpEmbeddedClientData) *
|
|
panel.max_embedded_client_count);
|
|
panel.embedded_client_list = (XtPointer) embedded_client_list;
|
|
}
|
|
|
|
embedded_client = &embedded_client_list[panel.embedded_client_count];
|
|
panel.embedded_client_count++;
|
|
|
|
embedded_client->pchResName = XtNewString (client_name);
|
|
embedded_client->wControl = control_data->icon;
|
|
embedded_client->winParent = None;
|
|
embedded_client->pCD = NULL;
|
|
}
|
|
|
|
for (i = 0; i < panel.embedded_client_count - 1; i++)
|
|
{
|
|
embedded_client = &embedded_client_list[i];
|
|
if (embedded_client->pCD != NULL)
|
|
embedded_client->pCD->pECD = (void *) embedded_client;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < panel.embedded_client_count; i++)
|
|
{
|
|
if (embedded_client_list[i].wControl == control_data->icon)
|
|
{
|
|
Position remove_y;
|
|
Dimension adjust_y = 0;
|
|
|
|
|
|
/* This block will reparent the client window, move it */
|
|
/* to a new window location, and remap the window. */
|
|
|
|
if (embedded_client_list[i].pCD != NULL)
|
|
{
|
|
client_window = embedded_client_list[i].pCD->client;
|
|
UnManageWindow (embedded_client_list[i].pCD);
|
|
XSync (XtDisplay (panel.shell), False);
|
|
XMoveWindow (XtDisplay (panel.shell), client_window, 0, 0);
|
|
XMapWindow (XtDisplay (panel.shell), client_window);
|
|
}
|
|
|
|
remove_y = embedded_client_list[i].y;
|
|
|
|
|
|
/* deleted control height plus 5 pixels of form offset */
|
|
|
|
if(control_data->icon) {
|
|
adjust_y = XtHeight (control_data->icon) + 5;
|
|
}
|
|
|
|
panel.embedded_client_count--;
|
|
|
|
XtFree (embedded_client_list[i].pchResName);
|
|
|
|
for (j = i; j < panel.embedded_client_count; j++)
|
|
{
|
|
embedded_client_list[j] = embedded_client_list[j + 1];
|
|
embedded_client = &embedded_client_list[j];
|
|
|
|
if (embedded_client_list[i].pCD != NULL)
|
|
{
|
|
embedded_client->pCD->pECD = (void *) embedded_client;
|
|
|
|
if (control_data->icon && XtParent(control_data->icon) ==
|
|
XtParent(embedded_client->wControl) &&
|
|
remove_y < embedded_client->y)
|
|
{
|
|
embedded_client->y -= adjust_y;
|
|
XMoveWindow(XtDisplay(panel.shell),
|
|
embedded_client->pCD->client,
|
|
embedded_client->x, embedded_client->y);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Set the embedded client list and count into the window manager's */
|
|
/* screen global data. */
|
|
|
|
EmbeddedClientSetData ();
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* EmbeddedClientSetData
|
|
* Set the embedded client list and count into the window manager's
|
|
* screen global data.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
EmbeddedClientSetData (void)
|
|
{
|
|
WmScreenData *pSD;
|
|
int i;
|
|
|
|
|
|
/* Find the screen which contains the front panel and set it */
|
|
/* embedded client list and count. */
|
|
|
|
for (i = 0; i < wmGD.numScreens; i++)
|
|
{
|
|
pSD = &(wmGD.Screens[i]);
|
|
|
|
if (pSD->managed)
|
|
{
|
|
if (pSD->wPanelist == panel.form)
|
|
{
|
|
pSD->pECD = (struct _WmFpEmbeddedClientData *) panel.embedded_client_list;
|
|
pSD->numEmbeddedClients = panel.embedded_client_count;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* EmbeddedClientSetGeometry
|
|
* Set the geometry and parenting window information for an
|
|
* embedded client control.
|
|
*
|
|
* Inputs: embedded_client_data - a pointer to the structure containing
|
|
* the embedded client information for a control.
|
|
*
|
|
* NOTE: Simplistic setting of position and size information. May need
|
|
* to base on resolution and component parent.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
EmbeddedClientSetGeometry (WmFpEmbeddedClientData * embedded_client_data)
|
|
|
|
|
|
{
|
|
Widget control;
|
|
|
|
control = embedded_client_data->wControl;
|
|
|
|
embedded_client_data->winParent = XtWindow (XtParent (control));
|
|
|
|
|
|
embedded_client_data->x = XtX (control) + 3;
|
|
embedded_client_data->y = XtY (control) + 3;
|
|
embedded_client_data->width = XtWidth (control) - 6;
|
|
embedded_client_data->height = XtHeight (control) - 6;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* PushRecallRegister
|
|
* This function adds a control to the list of push recall controls
|
|
* and resets, if necessary, the Window Managers pointers to the list.
|
|
*
|
|
* Inputs:
|
|
* control_data - the pointer to the ControlData * structure of
|
|
* the control to be installed or removed.
|
|
*
|
|
* install - Boolean indicating whether to add or remove the control
|
|
* from the push recall list.
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
PushRecallRegister (ControlData * control_data,
|
|
Boolean install)
|
|
|
|
|
|
{
|
|
char * client_name;
|
|
int i, j;
|
|
|
|
WmFpPushRecallClientList push_recall_list =
|
|
(WmFpPushRecallClientList) panel.push_recall_list;
|
|
|
|
WmFpPushRecallClientData * push_recall = NULL;
|
|
|
|
|
|
/* If this is a control installation, increase the list size, if */
|
|
/* needed, and initialize the push recall structure. If it is a */
|
|
/* removal, find the control in the push recall list and remove */
|
|
/* it by sliding each subsequent structure down one element in */
|
|
/* array. */
|
|
|
|
if (install)
|
|
{
|
|
client_name = (char *) control_data->element_values[CONTROL_CLIENT_NAME].parsed_value;
|
|
|
|
if (client_name == NULL)
|
|
client_name = (char *) control_data->element_values[CONTROL_LABEL].parsed_value;
|
|
|
|
|
|
/* First see if this is an update to an already installed */
|
|
/* push recall client. If so, simply update the icon field */
|
|
|
|
for (i = 0; i < panel.push_recall_count; i++)
|
|
{
|
|
if (strcmp (client_name, push_recall_list[i].pchResName) == 0)
|
|
{
|
|
push_recall_list[i].wControl = control_data->icon;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= panel.push_recall_count)
|
|
{
|
|
if (panel.push_recall_count == panel.max_push_recall_count)
|
|
{
|
|
panel.max_push_recall_count += 10;
|
|
push_recall_list = (WmFpPushRecallClientList)
|
|
XtRealloc ((char *) push_recall_list,
|
|
sizeof (WmFpPushRecallClientData) *
|
|
panel.max_push_recall_count);
|
|
panel.push_recall_list = (XtPointer) push_recall_list;
|
|
}
|
|
|
|
push_recall = &push_recall_list[panel.push_recall_count];
|
|
panel.push_recall_count++;
|
|
|
|
push_recall->pchResName = XtNewString (client_name);
|
|
push_recall->wControl = control_data->icon;
|
|
push_recall->pCD = NULL;
|
|
push_recall->tvTimeout.tv_sec = 0;
|
|
}
|
|
|
|
for (i = 0; i < panel.push_recall_count - 1; i++)
|
|
{
|
|
push_recall = &push_recall_list[i];
|
|
if (push_recall->pCD != NULL)
|
|
push_recall->pCD->pPRCD = (void *) push_recall;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < panel.push_recall_count; i++)
|
|
{
|
|
if (push_recall_list[i].wControl == control_data->icon)
|
|
{
|
|
panel.push_recall_count--;
|
|
|
|
XtFree (push_recall_list[i].pchResName);
|
|
|
|
for (j = i; j < panel.push_recall_count; j++)
|
|
{
|
|
push_recall_list[j] = push_recall_list[j + 1];
|
|
push_recall = &push_recall_list[j];
|
|
|
|
if (push_recall->pCD != NULL)
|
|
push_recall->pCD->pPRCD = (void *) push_recall;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Set the push recall list and count into the window manager's */
|
|
/* screen global data. */
|
|
|
|
PushRecallSetData ();
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* PushRecallSetData
|
|
* Set the push recall list and count into the window manager's
|
|
* screen global data.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
PushRecallSetData (void)
|
|
{
|
|
WmScreenData *pSD;
|
|
int i;
|
|
|
|
|
|
/* Find the screen which contains the front panel and set it */
|
|
/* push recall list and count. */
|
|
|
|
for (i = 0; i < wmGD.numScreens; i++)
|
|
{
|
|
pSD = &(wmGD.Screens[i]);
|
|
|
|
if (pSD->managed)
|
|
{
|
|
if (pSD->wPanelist == panel.form)
|
|
{
|
|
pSD->pPRCD = (struct _WmFpPushRecallClientData *) panel.push_recall_list;
|
|
pSD->numPushRecallClients = panel.push_recall_count;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* PushRecallGetData
|
|
* Find the index within the push recall list of the entry which
|
|
* contains the passed client name.
|
|
*
|
|
* Inputs:
|
|
* client_name - contains the name of the push recall client to
|
|
* be used for the lookup.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
int
|
|
PushRecallGetData (char * client_name)
|
|
|
|
|
|
{
|
|
WmFpPushRecallClientList push_recall_list =
|
|
(WmFpPushRecallClientList) panel.push_recall_list;
|
|
int i;
|
|
|
|
for (i = 0; i < panel.push_recall_count; i++)
|
|
if (strcmp (client_name, push_recall_list[i].pchResName) == 0)
|
|
return (i);
|
|
|
|
/* Should never get here */
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* WmPanelistWindowToSubpanel
|
|
* Get a panel widget given its shell window.
|
|
*
|
|
************************************************************************/
|
|
|
|
Widget
|
|
WmPanelistWindowToSubpanel (Display *dpy, Window win)
|
|
|
|
{
|
|
Widget subpanel_shell;
|
|
Widget * child_list;
|
|
int num_children;
|
|
|
|
Arg al[2];
|
|
int ac;
|
|
|
|
|
|
/* Get the widget for the subpanel (Should be only child of the shell!) */
|
|
|
|
subpanel_shell = XtWindowToWidget (dpy, win);
|
|
|
|
ac = 0;
|
|
XtSetArg (al[ac], XmNchildren, &child_list); ac++;
|
|
XtSetArg (al[ac], XmNnumChildren, &num_children); ac++;
|
|
XtGetValues (subpanel_shell, al, ac);
|
|
|
|
return ((num_children > 0) ? child_list[0] : (Widget)NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* WmPanelistSetBusy
|
|
* Turn on or off the busy light.
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
WmFrontPanelSetBusy (Boolean on)
|
|
|
|
{
|
|
if (panel.busy_light_data != NULL)
|
|
_DtControlSetBusy (panel.busy_light_data->icon, on);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* SetGeometry
|
|
* set x and y based on given geometry
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
SetGeometry (Widget w, String geometry, Position * x, Position * y)
|
|
|
|
{
|
|
int x_return, y_return;
|
|
unsigned int width_return, height_return;
|
|
long flags;
|
|
|
|
flags = XParseGeometry (geometry, &x_return, &y_return,
|
|
&width_return, &height_return);
|
|
|
|
if (flags)
|
|
{
|
|
if (flags & XValue)
|
|
*x = (Position) x_return;
|
|
|
|
if (flags & XNegative)
|
|
*x = (Position) (WidthOfScreen (XtScreen (w)) - XtWidth(w))
|
|
+ x_return;
|
|
|
|
if (flags & YValue)
|
|
*y = (Position) y_return;
|
|
|
|
if (flags & YNegative)
|
|
{
|
|
*y = (Position) (HeightOfScreen (XtScreen (w)) - XtHeight(w))
|
|
+ y_return;
|
|
}
|
|
|
|
if (flags & XValue || flags & YValue || flags & XNegative ||
|
|
flags & YNegative)
|
|
{
|
|
XtMoveWidget (w, *x, *y);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* WmPanelistShow
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
WmPanelistShow (Widget w)
|
|
|
|
{
|
|
SwitchData * switch_data;
|
|
Dimension switch_rc_height;
|
|
Dimension switch_button_height;
|
|
|
|
Dimension width = XtWidth(panel.shell);
|
|
Dimension height = XtHeight(panel.shell);
|
|
Position x = XtX(panel.shell);
|
|
Position y = XtY(panel.shell);
|
|
Dimension screen_width;
|
|
|
|
Display * display;
|
|
|
|
CompositeWidget cw;
|
|
Widget * widget_list;
|
|
DtWmHints vHints;
|
|
|
|
String shell_geometry = NULL;
|
|
char geometry_buffer[32];
|
|
|
|
XSizeHints hints;
|
|
long supplied;
|
|
|
|
int i;
|
|
Arg al[20];
|
|
int ac;
|
|
|
|
/* Find the switch data for later processing */
|
|
|
|
switch_data = NULL;
|
|
|
|
for (i = 0; i < panel.box_data_count; i++)
|
|
{
|
|
if (panel.box_data[i]->switch_data != NULL)
|
|
{
|
|
switch_data = panel.box_data[i]->switch_data;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Realize the shell so that it is sized properly for later */
|
|
/* positioning and child repositioning. */
|
|
|
|
XtRealizeWidget (panel.shell);
|
|
|
|
|
|
/* See if a geometry has been set. */
|
|
|
|
ac = 0;
|
|
XtSetArg (al[ac], XmNgeometry, &shell_geometry); ac++;
|
|
XtGetValues (panel.shell, al, ac);
|
|
|
|
|
|
/* If the shell has no default geometry, construct a default */
|
|
/* which will center the panel along the bottom of the display */
|
|
|
|
width = XtWidth (panel.shell);
|
|
screen_width = WidthOfScreen (XtScreen (panel.shell));
|
|
display = XtDisplay (panel.shell);
|
|
|
|
if (shell_geometry == NULL)
|
|
{
|
|
Position x;
|
|
|
|
if (panel.element_values[PANEL_GEOMETRY].string_value != NULL)
|
|
{
|
|
shell_geometry = panel.element_values[PANEL_GEOMETRY].parsed_value;
|
|
}
|
|
else
|
|
{
|
|
x = (screen_width > width) ? (Position)(screen_width - width) / 2 : 0;
|
|
snprintf (geometry_buffer, 32 - 1, "+%d-0", x);
|
|
shell_geometry = geometry_buffer;
|
|
}
|
|
|
|
XtSetArg (al[0], XmNgeometry, shell_geometry);
|
|
XtSetValues (panel.shell, al, 1);
|
|
}
|
|
|
|
|
|
/* Adjust the positions of the buttons within the switch */
|
|
/* so that they are spaced nicely. */
|
|
|
|
if (switch_data != NULL)
|
|
{
|
|
UpdateSwitchGeometry (switch_data->box_data);
|
|
|
|
|
|
/* Reposition or adjust the front panel if it is either off */
|
|
/* the right edge of the screen or larger than the screen */
|
|
|
|
if (width > screen_width)
|
|
{
|
|
Arg al[1];
|
|
|
|
while (width > screen_width &&
|
|
panel.switch_row_count < switch_data->switch_count)
|
|
{
|
|
panel.switch_row_count++;
|
|
|
|
XtSetArg (al[0], XmNnumColumns, panel.switch_row_count);
|
|
XtSetValues (switch_data->rc, al, 1);
|
|
|
|
width = XtWidth (panel.shell);
|
|
}
|
|
}
|
|
}
|
|
|
|
SetGeometry (panel.shell, shell_geometry, &x, &y);
|
|
WorkspaceAdjustPanelPosition (x, y, XtWidth (panel.shell),
|
|
XtHeight (panel.shell));
|
|
|
|
|
|
/* Set hints to avoid interactive placement */
|
|
|
|
if (XGetWMNormalHints(display, XtWindow(panel.shell),
|
|
&hints, &supplied) != 0)
|
|
{
|
|
hints.flags |= USPosition|USSize;
|
|
XSetWMNormalHints(display, XtWindow(panel.shell), &hints);
|
|
}
|
|
|
|
|
|
/* Set the shells icon and title for when it is minimized */
|
|
|
|
if (switch_data != NULL)
|
|
{
|
|
int current_workspace = switch_data->active_switch;
|
|
|
|
XtSetArg (al[0], XmNiconName, switch_data->switch_names[current_workspace]);
|
|
XtSetArg (al[1], XmNtitle, switch_data->switch_names[current_workspace]);
|
|
XtSetValues (panel.shell, al, 2);
|
|
}
|
|
|
|
|
|
/* Set panel's window manager hints. */
|
|
|
|
vHints.flags = DtWM_HINTS_BEHAVIORS;
|
|
vHints.behaviors = DtWM_BEHAVIOR_PANEL;
|
|
_DtWsmSetDtWmHints (XtDisplay(panel.shell), XtWindow (panel.shell), &vHints);
|
|
|
|
|
|
/* Set the subpanel's transientShell to update transientFor and */
|
|
/* Set the subpanel hints. */
|
|
|
|
vHints.behaviors |= DtWM_BEHAVIOR_SUBPANEL;
|
|
vHints.flags |= DtWM_HINTS_ATTACH_WINDOW;
|
|
vHints.attachWindow = XtWindow (panel.shell);
|
|
|
|
for (i = 0, widget_list = M_PopupList (panel.shell);
|
|
i < M_NumPopups (panel.shell); i++)
|
|
{
|
|
cw = (CompositeWidget) widget_list[i];
|
|
|
|
ac = 0;
|
|
XtSetArg (al[ac], XmNtransientFor, NULL); ac++;
|
|
XtSetValues ((Widget) cw, al, ac);
|
|
|
|
ac = 0;
|
|
XtSetArg (al[ac], XmNtransientFor, panel.shell); ac++;
|
|
XtSetValues ((Widget) cw, al, ac);
|
|
|
|
if (M_NumChildren (cw) > 0)
|
|
{
|
|
XtRealizeWidget ((M_Children (cw))[0]);
|
|
_DtWsmSetDtWmHints (XtDisplay (panel.shell),
|
|
XtWindow (widget_list[i]), &vHints);
|
|
}
|
|
}
|
|
|
|
|
|
/* Set the push recall list and count into the window manager's */
|
|
/* screen global data. */
|
|
|
|
PushRecallSetData ();
|
|
|
|
|
|
/* Set up the callback ot the workspace management API for */
|
|
/* catching changes in workspace configuration. */
|
|
|
|
DtWsmAddWorkspaceModifiedCallback(panel.shell,
|
|
WorkspaceModifyCB, (XtPointer)switch_data);
|
|
|
|
|
|
/* Get the front panel displayed */
|
|
|
|
XtSetMappedWhenManaged (panel.shell, True);
|
|
XtPopup (panel.shell, XtGrabNone);
|
|
|
|
|
|
/* Restore the session information */
|
|
|
|
SessionRestoreData ();
|
|
|
|
|
|
/* Set up the window and geometry information for the embedded clients */
|
|
|
|
for (i = 0; i < panel.embedded_client_count; i++)
|
|
EmbeddedClientSetGeometry (&(((WmFpEmbeddedClientList) panel.embedded_client_list)[i]));
|
|
|
|
|
|
/* Set the embedded client list and count into the window manager's */
|
|
/* screen global data. */
|
|
|
|
EmbeddedClientSetData ();
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* WmPanelistAllocate
|
|
*
|
|
************************************************************************/
|
|
|
|
Widget
|
|
WmPanelistAllocate (Widget w,
|
|
XtPointer global_data,
|
|
XtPointer screen_data)
|
|
|
|
{
|
|
Boolean create_fp;
|
|
|
|
panel.app_name = wmGD.mwmName;
|
|
create_fp = FrontPanelReadDatabases ();
|
|
|
|
if (create_fp)
|
|
{
|
|
#ifdef DT_PERFORMANCE
|
|
_DtPerfChkpntMsgSend("Begin creating front panel");
|
|
#endif
|
|
|
|
FrontPanelCreate (w);
|
|
|
|
#ifdef DT_PERFORMANCE
|
|
_DtPerfChkpntMsgSend("End creating front panel");
|
|
#endif
|
|
|
|
panel.global_data = global_data;
|
|
panel.screen_data = screen_data;
|
|
|
|
return (panel.form);
|
|
}
|
|
else
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* WmSubpanelPosted
|
|
* Add an event handler to catch when the subpanel is torn off. The
|
|
* event handler will then change the subpanel's behavior to remain
|
|
* displayed after a control is selected.
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
WmSubpanelPosted (Display * display,
|
|
Window shell_window)
|
|
|
|
{
|
|
BoxData * box_data;
|
|
ControlData * main_control_data;
|
|
SubpanelData * subpanel_data;
|
|
|
|
int i, j;
|
|
|
|
|
|
/* Loop through the main controls to find the subpanel whose */
|
|
/* window matches the parameter shell window and then add the */
|
|
/* event handler for tear off behavoir. */
|
|
|
|
for (i = 0; i < panel.box_data_count; i++)
|
|
{
|
|
box_data = panel.box_data[i];
|
|
|
|
for (j = 0; j < box_data->control_data_count; j++)
|
|
{
|
|
main_control_data = box_data->control_data[j];
|
|
|
|
if (main_control_data->subpanel_data != NULL &&
|
|
XtWindow (main_control_data->subpanel_data->shell) == shell_window)
|
|
{
|
|
subpanel_data = main_control_data->subpanel_data;
|
|
|
|
subpanel_data->posted_x = XtX (subpanel_data->shell);
|
|
|
|
XtAddEventHandler (subpanel_data->shell, StructureNotifyMask, False,
|
|
(XtEventHandler) SubpanelTornEventHandler,
|
|
(XtPointer) main_control_data);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|