1 /* XView Onroot Icon from Pixmap creation.
2 Copyright (C) 1995 Jakub Jelinek.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #include <X11/Xutil.h>
25 #include <X11/extensions/shape.h>
26 #include <xview/xview.h>
27 #include <xview/frame.h>
28 #include <xview/dragdrop.h>
29 #include <xview/font.h>
30 #include <xview/defaults.h>
33 #include "ext.h" /* regex_command */
40 static char *file_xpm
[] = {
41 /* width height ncolors chars_per_pixel */
50 "dddd``````````````````dddddddddd",
51 "dddd`eeeeeeeeeeeeeeee``ddddddddd",
52 "dddd`eeeeeeeeeeeeeeee`a`dddddddd",
53 "dddd`eeeeeeeeeeeeeeee`aa`ddddddd",
54 "dddd`eeeeeeeeeeeeeeee`aaa`dddddd",
55 "dddd`eeeeeeeeeeeeeeee`aaaa`ddddd",
56 "dddd`eeeeeeeeeeeeeeee```````dddd",
57 "dddd`eeeeeeeeeeeeeeeeeaaaaa`cddd",
58 "dddd`eeeeeeeeeeeeeeeeeeaaaa`cddd",
59 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
60 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
61 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
62 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
63 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
64 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
65 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
66 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
67 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
68 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
69 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
70 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
71 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
72 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
73 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
74 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
75 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
76 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
77 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
78 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
79 "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
80 "dddd````````````````````````cddd",
81 "dddddccccccccccccccccccccccccddd"
85 static Screen
*screen
;
86 #define root XRootWindowOfScreen(screen)
87 static Colormap colormap
;
89 extern Dlg_head
*midnight_dlg
;
93 int btn_down_x
, btn_down_y
;
94 struct timeval prev_time
;
95 } click_info
= { XV_NULL
, 0, 0, {0, 0}};
96 static int xv_icon_grab
= 0, xv_icon_drag
= 0;
97 static int wait_for_btnup
= 0;
99 static int last_x
, last_y
, offset_x
, offset_y
;
100 static xv_icondep_frame
= XV_NULL
;
101 static char *xv_icondep_free
= NULL
;
103 static void draw_borderrect (Window win
, Xv_window xv_win
, int x
, int y
)
107 width
= xv_get (xv_win
, XV_WIDTH
);
108 height
= xv_get (xv_win
, XV_HEIGHT
);
110 XDrawRectangle (dpy
, win
, xor_gc
, x
, y
, width
, height
);
113 struct xviconruncommand
{
119 void xvIconRunCommand (struct xviconruncommand
*xirc
)
122 droplist
[0] = xirc
->drops
;
125 regex_command (x_basename (xirc
->filename
), xirc
->action
, droplist
, NULL
);
126 free (xirc
->filename
);
128 if (xirc
->drops
!= NULL
)
133 void XvIconRunCommand (Frame frame
, char *action
, char *drops
)
135 XpmIcon
*icon
= (XpmIcon
*) xv_get (frame
, WIN_CLIENT_DATA
);
136 struct xviconruncommand
*xirc
= (struct xviconruncommand
*)
137 xmalloc (sizeof (struct xviconruncommand
), "XvIconRunCommand");
139 xirc
->filename
= strdup (icon
->filename
);
140 xirc
->action
= strdup (action
);
142 xirc
->drops
= strdup (drops
);
146 xv_post_proc (midnight_dlg
, (void (*)(void *))xvIconRunCommand
,
150 void XvIconDepMenu (Menu menu
, Menu_item item
)
152 char *p
= (char *) xv_get (item
, MENU_STRING
);
154 if (!strcmp (p
, "Close")) {
155 DeleteXpmIcon ((XpmIcon
*) xv_get (xv_icondep_frame
, WIN_CLIENT_DATA
));
156 xv_destroy_safe (xv_icondep_frame
);
159 XvIconRunCommand (xv_icondep_frame
, p
, NULL
);
162 free (xv_icondep_free
);
165 void XpmIconEvent (Xv_window frame
, Event
*event
)
168 if (event_action (event
) == LOC_DRAG
) {
169 draw_borderrect (root
, frame
, last_x
, last_y
);
170 last_x
= event_x (event
) - offset_x
;
171 last_y
= event_y (event
) - offset_y
;
172 draw_borderrect (root
, frame
, last_x
, last_y
);
174 } else if (event_is_button (event
)) {
175 if (event_is_down (event
))
177 } else if (!event_is_iso (event
))
179 draw_borderrect (root
, frame
, last_x
, last_y
);
180 last_x
= event_x (event
) - offset_x
;
181 last_y
= event_y (event
) - offset_y
;
188 XFreeGC (dpy
, xor_gc
);
190 } else if (xv_icon_grab
) {
191 if (wait_for_btnup
) {
192 if (event_action (event
) == LOC_DRAG
) {
193 static int threshold
;
194 static int dist_x
, dist_y
;
197 threshold
= defaults_get_integer (
198 "mxc.clickmovethreshold",
199 "Mxc.ClickMoveThreshold", 10);
201 dist_x
= event_x (event
) - click_info
.btn_down_x
;
204 dist_y
= event_y (event
) - click_info
.btn_down_y
;
207 if (!xv_icon_drag
&& (dist_x
> threshold
|| dist_y
> threshold
||
208 event_ctrl_is_down (event
) || event_shift_is_down (event
))) {
209 xor_gc
= XCreateGC (dpy
, xv_get (frame
, XV_XID
), 0, 0);
210 XSetForeground (dpy
, xor_gc
, xv_get (frame
, WIN_FOREGROUND_COLOR
));
211 XSetFunction (dpy
, xor_gc
, GXxor
);
212 XSetLineAttributes (dpy
, xor_gc
, 2, LineSolid
, CapNotLast
, JoinRound
);
213 last_x
= xv_get (frame
, XV_X
);
214 last_y
= xv_get (frame
, XV_Y
);
215 offset_x
= event_x (event
) - last_x
;
216 offset_y
= event_y (event
) - last_y
;
217 draw_borderrect (root
, frame
, last_x
, last_y
);
222 if (event_is_button (event
) && event_is_down (event
)) {
225 if (event_action (event
) == ACTION_SELECT
) {
226 if (is_dbl_click (&click_info
.prev_time
, &event_time (event
))) {
227 click_info
.prev_time
.tv_sec
= 0;
228 click_info
.prev_time
.tv_usec
= 0;
229 XvIconRunCommand (frame
, "Open", NULL
);
231 click_info
.prev_time
= event_time (event
);
236 if (event_action (event
) == ACTION_ADJUST
) {
240 if (!event_is_button (event
) && !event_is_iso (event
))
246 switch (event_action (event
)) {
247 case ACTION_DRAG_PREVIEW
:
249 case ACTION_DRAG_COPY
:
250 case ACTION_DRAG_MOVE
:
251 case ACTION_DRAG_LOAD
:
254 Selection_requestor sel
= (Selection_requestor
)
255 xv_get (frame
, XV_KEY_DATA
, KEY_DATA_SELREQ
);
257 if ((ds
= dnd_decode_drop (sel
, event
)) != XV_ERROR
) {
261 xv_set (sel
, SEL_TYPE
, XA_STRING
, NULL
);
262 q
= (char *) xv_get (sel
, SEL_DATA
, &length
, &format
);
263 if (length
!= SEL_ERROR
) {
264 XvIconRunCommand (frame
, "Drop", q
);
267 xv_set (sel
, SEL_TYPE_NAME
, "_SUN_SELECTION_END", 0);
268 xv_get (sel
, SEL_DATA
, &length
, &format
);
274 if (event_is_down (event
)) {
278 if (event_is_down (event
)) {
279 static Menu menu
= XV_NULL
;
286 filename
= ((XpmIcon
*) xv_get (frame
, WIN_CLIENT_DATA
))->filename
;
287 menu
= (Menu
) xv_create (XV_NULL
, MENU
,
288 MENU_NOTIFY_PROC
, XvIconDepMenu
,
289 MENU_TITLE_ITEM
, x_basename (filename
),
290 MENU_STRINGS
, "Close", "Open", "View", "Edit", NULL
,
292 p
= regex_command (x_basename (filename
), NULL
, NULL
, NULL
);
295 while (*p
== ' ' || *p
== '\t')
300 while (*q
&& *q
!= ' ' && *q
!= '\t')
314 xv_icondep_frame
= frame
;
316 menu_show (menu
, frame
, event
, NULL
);
321 if (event_is_down (event
)) {
322 if (click_info
.frame
!= frame
) {
323 click_info
.frame
= frame
;
324 click_info
.prev_time
.tv_sec
= 0;
325 click_info
.prev_time
.tv_usec
= 0;
327 click_info
.btn_down_x
= event_x (event
);
328 click_info
.btn_down_y
= event_y (event
);
335 XpmIcon
*CreateXpmIcon (char *iconname
, int x
, int y
, char *title
)
340 XpmIcon
*view
= xmalloc (sizeof (*view
), "CreateXpmIcon");
343 Font_string_dims fontdims
;
345 XImage
*ximage
, *shapeimage
;
347 static char *fontname
= NULL
;
349 int titlelen
= strlen (title
);
351 screen
= ScreenOfDisplay (dpy
,
352 (int) xv_get ((Xv_Screen
) xv_get (mcframe
, XV_SCREEN
), SCREEN_NUMBER
));
354 colormap
= XDefaultColormapOfScreen(screen
);
355 memset (view
, 0, sizeof (*view
));
357 frame
= xv_create (mcframe
, FRAME
,
363 WIN_CONSUME_EVENTS
, WIN_MOUSE_BUTTONS
, WIN_UP_EVENTS
, LOC_DRAG
, NULL
,
364 WIN_EVENT_PROC
, XpmIconEvent
,
365 WIN_CLIENT_DATA
, view
,
368 win
= (Window
) xv_get (frame
, XV_XID
);
370 view
->attributes
.valuemask
|= XpmReturnInfos
;
371 view
->attributes
.valuemask
|= XpmReturnPixels
| XpmCloseness
;
372 view
->attributes
.closeness
= 40000;
374 ErrorStatus
= XpmReadFileToImage(dpy
, iconname
,
375 &ximage
, &shapeimage
,
377 if (ErrorStatus
!= XpmSuccess
)
378 ErrorStatus
= XpmCreateImageFromData(dpy
, file_xpm
,
379 &ximage
, &shapeimage
,
382 if (ErrorStatus
!= XpmSuccess
) {
384 xv_destroy_safe (frame
);
389 fontname
= defaults_get_string ("mxc.iconfont", "Mxc.IconFont", "");
392 font
= xv_find (mcframe
, FONT
,
396 font
= xv_get (mcframe
, XV_FONT
);
397 xv_get (font
, FONT_STRING_DIMS
, title
, &fontdims
);
398 xfs
= (XFontStruct
*) xv_get (font
, FONT_INFO
);
399 width
= view
->attributes
.width
;
400 if (view
->attributes
.width
< fontdims
.width
)
401 view
->attributes
.width
= fontdims
.width
;
402 height
= view
->attributes
.height
;
403 view
->attributes
.height
+= fontdims
.height
;
405 view
->pixmap
= XCreatePixmap (dpy
, win
, view
->attributes
.width
,
406 view
->attributes
.height
, ximage
->depth
);
407 gc
= XCreateGC (dpy
, view
->pixmap
, 0, NULL
);
408 XSetForeground (dpy
, gc
, BlackPixelOfScreen (screen
));
409 XFillRectangle (dpy
, view
->pixmap
, gc
, 0, 0, view
->attributes
.width
,
410 view
->attributes
.height
);
411 XPutImage (dpy
, view
->pixmap
, gc
, ximage
, 0, 0,
412 (view
->attributes
.width
- width
) / 2, 0, width
, height
);
414 view
->mask
= XCreatePixmap (dpy
, win
, view
->attributes
.width
,
415 view
->attributes
.height
, 1);
416 gc
= XCreateGC (dpy
, view
->mask
, 0, NULL
);
417 XSetFont (dpy
, gc
, xv_get (font
, XV_XID
));
418 XSetForeground (dpy
, gc
, 0);
419 XFillRectangle (dpy
, view
->mask
, gc
, 0, 0, view
->attributes
.width
,
420 view
->attributes
.height
);
421 XSetForeground (dpy
, gc
, 1);
422 if (shapeimage
!= NULL
)
423 XPutImage (dpy
, view
->mask
, gc
, shapeimage
, 0, 0,
424 (view
->attributes
.width
- width
) / 2, 0, width
, height
);
426 XFillRectangle (dpy
, view
->mask
, gc
,
427 (view
->attributes
.width
- width
) / 2, 0, width
, height
);
428 XDrawString (dpy
, view
->mask
, gc
,
429 (view
->attributes
.width
- fontdims
.width
) / 2, height
+ xfs
->ascent
,
432 XDestroyImage (ximage
);
433 if (shapeimage
!= NULL
)
434 XDestroyImage (shapeimage
);
437 XV_X
, x
- view
->attributes
.width
/ 2,
438 XV_Y
, y
- view
->attributes
.height
/ 2,
439 XV_WIDTH
, view
->attributes
.width
,
440 XV_HEIGHT
, view
->attributes
.height
,
443 XSetWindowBackgroundPixmap(dpy
, win
, view
->pixmap
);
446 XShapeCombineMask(dpy
, win
, ShapeBounding
, 0, 0,
447 view
->mask
, ShapeSet
);
449 XClearWindow(dpy
, win
);
453 rect
.r_width
= view
->attributes
.width
;
454 rect
.r_height
= view
->attributes
.height
;
456 xv_create (frame
, DROP_SITE_ITEM
,
457 DROP_SITE_EVENT_MASK
, DND_ENTERLEAVE
,
458 DROP_SITE_REGION
, &rect
,
461 XV_KEY_DATA
, KEY_DATA_SELREQ
,
462 xv_create (frame
, SELECTION_REQUESTOR
, NULL
),
474 void DeleteXpmIcon (XpmIcon
*view
)
477 XFreePixmap(dpy
, view
->pixmap
);
479 XFreePixmap(dpy
, view
->mask
);
481 XFreeColors(dpy
, colormap
,
482 view
->attributes
.pixels
, view
->attributes
.npixels
, 0);
484 XpmFreeAttributes(&view
->attributes
);
487 free (view
->filename
);