/*-
* Copyright (c) 2001 Jordan DeLong
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "pier.h"
/* used for dragging the pier with button2 */
static pier_t *current_pier = NULL;
static int drag_x, drag_y;
/* flag if we use double clicks for launching */
static int pier_singleclick;
/* do we allow pier moving */
static int pier_nodragging;
/* handle map requests when we launch apps to dock/swallow */
static int map_request(int pcall, screen_t *screen, XMapRequestEvent *e) {
XClassHint classhint;
comtab_t *comtab;
int ret;
ret = PLUGIN_OK;
/* we have to check new windows if we are waiting for a dock/swallowed win */
if (!LIST_EMPTY(&comtab_list)) {
if (XGetClassHint(display, e->window, &classhint) == 0)
return PLUGIN_OK;
/* see if this is a WM_CLASS we a looking for */
LIST_FOREACH(comtab, &comtab_list, ct_list)
if (strcmp(comtab->classhint.res_class, classhint.res_class) == 0
&& strcmp(comtab->classhint.res_name,
classhint.res_name) == 0) {
pier_gotcom(comtab, e);
ret = PLUGIN_USING;
goto free1;
}
free1:
XFree(classhint.res_name);
XFree(classhint.res_class);
}
return ret;
}
/* x event handler for button presses */
static int button_press(XButtonEvent *e) {
pier_t *pier;
Window dumwin;
/* button 2 drags the pier */
if (pier_nodragging || e->button != Button2)
return PLUGIN_OK;
if (!(pier = pier_findpier(e->window)))
return PLUGIN_OK;
current_pier = pier;
if (!XTranslateCoordinates(display, e->root, pier->window, e->x_root,
e->y_root, &drag_x, &drag_y, &dumwin)) {
current_pier = NULL;
return PLUGIN_OK;
}
return PLUGIN_OK;
}
/* x event handler for button release */
static int button_release(XButtonEvent *e) {
static long lasttime;
static int gotfirst = 0;
pier_t *pier;
if (current_pier) {
current_pier = NULL;
return PLUGIN_OK;
} else if (e->button != Button1)
return PLUGIN_OK;
else if ((pier = pier_findpier(e->window)) == NULL)
return PLUGIN_OK;
if (pier_singleclick) {
if (e->x >= 0 && e->y >= 0
&& e->x < pier->width && e->y < pier->height)
pier_click(pier, e);
} else {
if (gotfirst && (e->time - lasttime <= 200)
&& e->x >= 0 && e->y >= 0
&& e->x < pier->width && e->y < pier->height) {
pier_click(pier, e);
gotfirst = 0;
} else {
lasttime = e->time;
gotfirst = 1;
}
}
return PLUGIN_OK;
}
/* pointer motion x event handler */
static int pointer_motion(XMotionEvent *e) {
int x, y;
if (!current_pier)
return PLUGIN_OK;
x = e->x_root - drag_x;
y = e->y_root - drag_y;
/* constrain movement */
if (x < 0)
x = 0;
else if (x + current_pier->width >= DisplayWidth(display, current_pier->screen))
x = DisplayWidth(display, current_pier->screen) - current_pier->width;
if (y < 0)
y = 0;
else if (y + current_pier->height >= DisplayHeight(display, current_pier->screen))
y = DisplayHeight(display, current_pier->screen) - current_pier->height;
/* move the window */
current_pier->x = x;
current_pier->y = y;
XMoveWindow(display, current_pier->window, x, y);
return PLUGIN_OK;
}
/* entry point for X11 events */
int xevent_handler(XEvent *e) {
switch (e->type) {
case ButtonPress:
button_press(&e->xbutton);
break;
case ButtonRelease:
button_release(&e->xbutton);
break;
case MotionNotify:
pointer_motion(&e->xmotion);
break;
}
return PLUGIN_OK;
}
/* parse params and such */
int init() {
pixmap_t *tile;
int size;
/* get basic parameters */
OPTIONAL_PARAM(&plugin_this->params, "singleclick", bool, pier_singleclick, 0);
OPTIONAL_PARAM(&plugin_this->params, "nodragging", bool, pier_nodragging, 0);
OPTIONAL_PARAM(&plugin_this->params, "tile_pixmap", pixmap, tile, NULL);
OPTIONAL_PARAM(&plugin_this->params, "tile_size", int, size, 64);
if (size <= 0 || size > 128)
size = 64;
if (pier_init(size, tile) == -1)
return PLUGIN_UNLOAD;
parseparams();
return PLUGIN_OK;
}
/* shutdown the pier */
void shutdown() {
pier_shutdown();
}
/* realize the pier; get ready for usage */
int start() {
/* register callbacks */
plugin_callback_add(plugin_this, PCALL_MAP_REQUEST, map_request);
if (pier_realize_all() == -1)
return PLUGIN_UNLOAD;
return PLUGIN_OK;
}
syntax highlighted by Code2HTML, v. 0.9.1